#include "fitz.h"
#include "mupdf.h"
#include "pdfapp.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>

#include <cairo.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>

#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stddef.h>
#include <locale.h>

cairo_surface_t *image;
GdkRectangle *drawable_region;
GdkCursor *cursor=NULL;
static Display *xdpy;
static GdkAtom xa_targets;
static GdkAtom xa_timestamp;
static GdkAtom xa_utf8_string;
static GdkAtom xa_string;
static int xscr;
static Window xwin;
static GC xgc;
static int mapped = 0;
static Cursor xcarrow, xchand, xcwait;
static int justcopied = 0;
static int dirty = 0;
static char *password = "";
static int reqw = 0;
static int reqh = 0;
static char copylatin1[1024 * 16] = "";
static char copyutf8[1024 * 48] = "";
static Time copytime;
static char *filename;
static pdfapp_t gapp;
static int closing = 0;

GtkAdjustment* adjustmentx;
GtkAdjustment* adjustmenty;

static GtkWidget *gwindow, *gimage, *scroll;

static void gtk_create_image(pdfapp_t *app);

static void
ui_add_widget (GtkUIManager *ui, GtkWidget *widget, GtkContainer *container)
{
  gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
  gtk_widget_show (widget);
}

GdkPixbuf *create_pixbuf(const gchar * filename)
{
  GdkPixbuf *pixbuf;
  GError *error = NULL;
  pixbuf = gdk_pixbuf_new_from_file(filename, &error);
  if(!pixbuf) {
    fprintf(stderr, "%s\n", error->message);
    g_error_free(error);
  }
  return pixbuf;
}

void winscrollbar(pdfapp_t *app){
  adjustmentx = gtk_range_get_adjustment (GTK_RANGE(GTK_SCROLLED_WINDOW(scroll)->hscrollbar));
  adjustmenty = gtk_range_get_adjustment (GTK_RANGE(GTK_SCROLLED_WINDOW(scroll)->vscrollbar));
  /* printf("\n lower %f upper %f page-size %f step-increment %f page-increment %f value %f panx %d pany %d", adjustmentx->lower, adjustmentx->upper, adjustmentx->page_size, adjustmentx->step_increment, adjustmentx->page_increment, adjustmentx->value,gapp.panx, gapp.pany); */
  /* printf("\n lower %f upper %f page-size %f step-increment %f page-increment %f value %f panx %d pany %d", adjustmenty->lower, adjustmenty->upper, adjustmenty->page_size, adjustmenty->step_increment, adjustmenty->page_increment, adjustmenty->value, gapp.panx, gapp.pany); */
  if(app->panx < 0)
  {
    adjustmentx->value = -app->panx;
    gtk_adjustment_changed(adjustmentx);
  }
  else if(app->panx > 0)
    gtk_adjustment_set_value(adjustmentx, 0);
  if(app->pany < 0)
  {
    adjustmenty->value = -app->pany;
    gtk_adjustment_changed(adjustmenty);
  }
  else if(app->pany > 0)
    gtk_adjustment_set_value(adjustmenty, 0);
}


static void on_mouse_cb(GtkWidget* widget,  GdkEventButton * event, gpointer data)
{
  int x, y;
  GdkModifierType state;
  /* printf("\n x %d y %d button %d  state %d type %d data %d \n", x, y, event->button, event->state, event->type, data); */
  gdk_window_get_pointer (widget->window, &x, &y, &state);
  if(gapp.image){
    if (data != 0 && justcopied){
        justcopied = 0;
        winrepaint(&gapp);
    }
    if(data == -1) copytime = gdk_event_get_time(event);
    pdfapp_onmouse(&gapp, x, y, event->button, (int)state, data);
    winblit(&gapp);
  }
}

static void on_mousewheel_cb(GtkWidget* widget,  GdkEventScroll * event, gpointer data)
{
  int x, y, button;
  GdkModifierType state;
  gdk_window_get_pointer (widget->window, &x, &y, &state);
  if(gapp.image){
    if (data != 0 && justcopied){
        justcopied = 0;
        winrepaint(&gapp);
    }
    if(event->direction == 0)
      button = 4;
    else if(event->direction == 1)
      button = 5;
    pdfapp_onmouse(&gapp, x, y, button, (int)state, data);
    winblit(&gapp);
  }
}

static void
on_clicked_cb (GtkAction *action, gpointer data){
  /* g_print ("Hello again - %d was pressed\n", data); */
  if (justcopied)
  {
    justcopied = 0;
    winrepaint(&gapp);
  }
  pdfapp_onkey(&gapp, (char)data);
  gtk_create_image(&gapp);
  gdk_window_invalidate_rect(gimage->window, drawable_region, TRUE);
  winblit(&gapp);
  /* winrepaint(&gapp); */
  /* pdfapp_onbutton(&gapp,) */
  /* printf("hello\n"); */
  /* printf(" %d \n", event->button); */  
}



GtkToolItem* gtk_create_item(gchar *stock_id, gchar *text) {
  GtkToolItem *open;
  GtkWidget *box;
  GtkWidget *label;
  GtkWidget *image;
  GtkWidget *button;

  open =  gtk_tool_item_new();
  gtk_tool_item_set_tooltip_text(open, "Open File..");
    
  box = gtk_vbox_new(FALSE, 0);

  image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_SMALL_TOOLBAR);
  label = gtk_label_new(text);

  gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0);
  /* gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); */
    
  button = gtk_button_new();

  gtk_container_add(GTK_CONTAINER(button), box);
  gtk_container_add(GTK_CONTAINER(open), button);

  if(g_strcasecmp (stock_id, GTK_STOCK_ZOOM_IN) == 0){
    g_signal_connect (button, "clicked", G_CALLBACK (on_clicked_cb), (gpointer)'+');
  }
  else if(g_strcasecmp (stock_id, GTK_STOCK_ZOOM_OUT) == 0){
    g_signal_connect (button, "clicked", G_CALLBACK (on_clicked_cb), (gpointer)'-');
  }
  else if(g_strcasecmp (stock_id, GTK_STOCK_GO_FORWARD) == 0){
    g_signal_connect (button, "clicked", G_CALLBACK (on_clicked_cb), (gpointer)' ');
  }
  else if(g_strcasecmp (stock_id, GTK_STOCK_GO_BACK) == 0){
    g_signal_connect (button, "clicked", G_CALLBACK (on_clicked_cb), (gpointer)'b');
  }



  return open;
}

static void
on_open_cb (GtkAction *action, gpointer data)
{
  GtkWidget *dialog;
  dialog = gtk_file_chooser_dialog_new (_("Select File"), GTK_WINDOW (gwindow),
                                        GTK_FILE_CHOOSER_ACTION_OPEN,
                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                        GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                        NULL);
  
  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
    gtk_widget_destroy (dialog);
    if(filename)
      {
        winloadfile(&gapp);
        int drawablex, drawabley;
        double step_x , step_y;
        gdk_drawable_get_size(gimage->window, &drawablex, &drawabley);
        step_x = (double)(drawablex)/gapp.image->w;
        step_y = (double)(drawabley)/gapp.image->h;
        gapp.resolution *= (step_x < step_y)? step_x : step_y;
        gapp.winw = drawablex;
        gapp.winh = drawabley;
        printf(" \n width %d  height %d  %d %d res %d step_x %f step_y %f winw %d winh %d \n", gapp.image->w, gapp.image->h, drawablex, drawabley, gapp.resolution, step_x, step_y, gapp.winw, gapp.winh);
        pdfapp_onload(&gapp);
        gtk_create_image(&gapp);
      }
    g_free (filename);
  }
}

static void
on_config_cb(GtkWindow *window, 
      GdkEvent *event, gpointer data)
{
  int drawablex, drawabley, width, height, neww, newh;
  adjustmentx = gtk_range_get_adjustment (GTK_RANGE(GTK_SCROLLED_WINDOW(scroll)->hscrollbar));
  adjustmenty = gtk_range_get_adjustment (GTK_RANGE(GTK_SCROLLED_WINDOW(scroll)->vscrollbar));
  gdk_drawable_get_size(gimage->window, &drawablex, &drawabley);
  /* gtk_window_get_size(GTK_WINDOW(scroll),&width,&height); */
  printf("\n drax %d dray %d regx %d regy %d  confx %d confy %d adx %f ady %f\n", drawablex, drawabley, gimage->allocation.width, gimage->allocation.height, event->configure.width, event->configure.height, adjustmentx->page_size, adjustmenty->page_size);
  if(gapp.image){
    /* 
     *   neww = event->configure.width - 4;
     *   newh = event->configure.height - 59;
     * pdfapp_onresize(&gapp, neww, newh);
     */
    pdfapp_onresize(&gapp, (int)adjustmentx->page_size, (int)adjustmenty->page_size);
    /* pdfapp_onresize(&gapp, scroll->allocation.width, scroll->allocation.height); */
  }
  winblit(&gapp);
  /* gtk_window_set_title(window, buf); */
}


static const GtkActionEntry menu_entries[] =
  {
    { "File", NULL, N_("_File") },
    { "Edit", NULL, N_("_Edit") },
    { "View", NULL, N_("_View") },
    { "Tools", NULL, N_("_Tools") },
    { "Window", NULL, N_("_Window") },
    { "Help", NULL, N_("_Help") },
    { "Open", GTK_STOCK_FIND, N_("_Open Files"), "<control>O",
      N_("Search for open files"), G_CALLBACK(on_open_cb) }
  };

static const char ui_info[] =
  "  <menubar name=\"MenuBar\">"
  "    <menu name=\"FileMenu\" action=\"File\">"
  "      <menuitem name=\"FileOpenMenu\" action=\"Open\" />"
  "      <menuitem name=\"FileCloseMenu\" action=\"Close\" />"
  "      <menuitem name=\"FileSaveMenu\" action=\"Save\" />"
  "      <menuitem name=\"FileSaveAsMenu\" action=\"Save as\" />"
  "      <menuitem name=\"FilePrintMenu\" action=\"Print\" />"
  "      <menuitem name=\"FileExitMenu\" action=\"Exit\" />"
  "    </menu>"
  "    <menu name=\"EditMenu\" action=\"Edit\">"
  "    </menu>"
  "    <menu name=\"ViewMenu\" action=\"View\">"
  "    </menu>"
  "    <menu name=\"ToolsMenu\" action=\"Tools\">"
  "    </menu>"
  "    <menu name=\"WindowMenu\" action=\"Window\">"
  "    </menu>"    
  "    <menu name=\"HelpMenu\" action=\"Help\">"
  "      <menuitem name=\"HelpContentsMenu\" action=\"HelpContents\" />"
  "      <menuitem name=\"HelpAboutMenu\" action=\"About\" />"
  "    </menu>"
  "  </menubar>";



/*
 * Dialog boxes
 */

void winwarn(pdfapp_t *app, char *msg)
{
  fprintf(stderr, "mupdf: %s\n", msg);
}

void winerror(pdfapp_t *app, fz_error error)
{
  fz_catch(error, "aborting");
  exit(1);
}

char *winpassword(pdfapp_t *app, char *filename)
{
  char *r = password;
  password = NULL;
  return r;
}

/*
 * X11 magic
 */


void winclose(pdfapp_t *app)
{
  closing = 1;
}

void wincursor(pdfapp_t *app, int curs)
{
  if(curs == ARROW)
    cursor = gdk_cursor_new (GDK_ARROW);
  else if(curs == HAND)
    cursor = gdk_cursor_new (GDK_HAND2);
  else if(curs == WAIT)
    cursor = gdk_cursor_new (GDK_WATCH);  
  gdk_window_set_cursor(gimage->window, cursor);  
}

void wintitle(pdfapp_t *app, char *s)
{
  
}

void winhelp(pdfapp_t *app)
{
  fprintf(stderr, "%s", pdfapp_usage(app));
}

void winresize(pdfapp_t *app, int w, int h)
{
  
}




void winrepaint(pdfapp_t *app)
{
  dirty = 1;
}

void windrawstringxor(pdfapp_t *app, int x, int y, char *s)
{
}

void windrawstring(pdfapp_t *app, int x, int y, char *s)
{
}

void windocopy(pdfapp_t *app)
{
	unsigned short copyucs2[16 * 1024];
	char *latin1 = copylatin1;
	char *utf8 = copyutf8;
	unsigned short *ucs2;
	int ucs;

	pdfapp_oncopy(&gapp, copyucs2, 16 * 1024);

	for (ucs2 = copyucs2; ucs2[0] != 0; ucs2++)
	{
		ucs = ucs2[0];

		utf8 += runetochar(utf8, &ucs);

		if (ucs < 256)
			*latin1++ = ucs;
		else
			*latin1++ = '?';
	}

	*utf8 = 0;
	*latin1 = 0;

	/* XSetSelectionOwner(xdpy, XA_PRIMARY, xwin, copytime); */
    /* gtk_selection_owner_set_for_display (gdk_display_get_default(),gimage, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); */
    gtk_selection_owner_set(gimage, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
    if(gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == gimage->window)
      printf("\n selection_owner\n");
    /* 
     * static GdkAtom targets_atom = GDK_NONE;
     * 
     * if (targets_atom == GDK_NONE)
     *   targets_atom = gdk_atom_intern ("UTF8_STRING", FALSE);
     * 
     * /\* And request the "TARGETS" target for the primary selection *\/
     * gtk_selection_convert (gimage, GDK_SELECTION_PRIMARY, targets_atom, GDK_CURRENT_TIME);
     */
    justcopied = 1;
}

gboolean on_selreq_cb(GtkWidget *widget,  GdkEventSelection *event, gpointer data){
  
    char *name1 = gdk_atom_name(event->target);
    char *name2 = gdk_atom_name(xa_targets);
    char *name3 = gdk_atom_name(xa_string);
    char *name4 = gdk_atom_name(xa_utf8_string);
    if(event->type == GDK_SELECTION_REQUEST)
      printf("\n name1 %s name2 %s name3 %s name4 %s\n",name1 ,name2, name3, name4);
    if (event->target == xa_targets)
	{
      GdkAtom atomlist[4];
      atomlist[0] = xa_targets;
      atomlist[1] = xa_timestamp;
      atomlist[2] = xa_string;
      atomlist[3] = xa_utf8_string;
      printf(" -> targets\n");
      XChangeProperty(xdpy, event->requestor, event->property, event->target,
                      32, PropModeReplace,
                      (unsigned char *)atomlist, sizeof(atomlist)/sizeof(Atom));
	}

	else if (event->target == xa_string)
	{
		XChangeProperty(xdpy, event->requestor, event->property, event->target,
			8, PropModeReplace, (unsigned char *)copylatin1, strlen(copylatin1));
        printf("\n string %s\n");
      /* gdk_property_change(gimage->window, event->property, event->target, 8, PropModeReplace, (unsigned char *)copylatin1, strlen(copylatin1)); */
	}
	else if (event->target == xa_utf8_string)
	{
            printf("\n utf8 string\n");
      /* gdk_property_change(gimage->window, event->property, event->target, 8, PropModeReplace, (unsigned char *)copyutf8, strlen(copyutf8)); */
      XChangeProperty(xdpy, event->requestor,event->property, event->target, 8, PropModeReplace, (unsigned char *)copyutf8, strlen(copyutf8));
    }
	else
	{
      printf("\n none");
		/* nevt.xselection.property = None; */
	}
    XSelectionEvent xevent;    
    xevent.type = SelectionNotify;
    xevent.serial = 0;
    xevent.send_event = True;
    xevent.requestor = event->requestor;
    xevent.selection = event->selection;
    xevent.target = event->target;
    if (event->property == GDK_NONE)
      xevent.property = None;
    else
      xevent.property = event->property;
    xevent.time = event->time;
    
    XSendEvent (xdpy, event->requestor, False, NoEventMask, (XEvent *)&xevent);
    /* 
     * gdk_selection_send_notify_for_display(gdk_x11_lookup_xdisplay(xdpy),
     *                                       event->requestor,
     *                                       event->selection,
     *                                       event->target,
     *                                       event->property,
     *                                       event->time);
     */
}
gboolean on_selrev_cb(GtkWidget *widget,  GtkSelectionData *selection_data, gpointer data){
  GdkAtom *atoms;
  GList *item_list;
  int i;

  /* printf("\nselction type %d display %d \n") */
  /* **** IMPORTANT **** Check to see if retrieval succeeded  */
  if (selection_data->length < 0){
      g_print ("Selection retrieval failed\n");
      return;
  }
  /* Make sure we got the data in the expected form */
  if (selection_data->type != GDK_SELECTION_TYPE_ATOM){
      g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
      return;
  }
  
  /* Print out the atoms we received */
  atoms = (GdkAtom *)selection_data->data;
  item_list = NULL;
  
  for (i=0; i<selection_data->length/sizeof(GdkAtom); i++){
    char *name;
    name = gdk_atom_name (atoms[i]);
    if (name != NULL)
      g_print ("%s\n",name);
    else
      g_print ("(bad atom)\n");
  }
  return;
}



void winopenuri(pdfapp_t *app, char *buf)
{
  char *browser = getenv("BROWSER");
  if (!browser)
    browser = "open";
  if (fork() == 0)
    execlp(browser, browser, buf, (char*)0);
}


static void gtk_create_image(pdfapp_t *app)
{
  /* printf("\n w %d h %d\n", app->image->w, app->image->h); */
  GdkPixbuf * pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, app->image->w, app->image->h);
  unsigned char *pixbuf_ptr = gdk_pixbuf_get_pixels(pixbuf);
  int x ,y;
  for (y = 0; y < app->image->h; ++y){
    unsigned char *ptr = (unsigned char *)app->image->samples + y*app->image->w*app->image->n;
    for (x = 0; x  < app->image->w; ++x){
      pixbuf_ptr[4*y*app->image->w+4*x] = ptr[4*x+2];
      pixbuf_ptr[4*y*app->image->w+4*x+1] = ptr[4*x+1];
      pixbuf_ptr[4*y*app->image->w+4*x+2] = ptr[4*x+0];
      pixbuf_ptr[4*y*app->image->w+4*x+3] = ptr[4*x+3];
    }
  }
  image = cairo_image_surface_create_for_data(gdk_pixbuf_get_pixels(pixbuf),
                                              CAIRO_FORMAT_ARGB32,
                                              app->image->w,
                                              app->image->h,
                                              gdk_pixbuf_get_rowstride(pixbuf));
}

void winreloadfile(pdfapp_t *app)
{
  int fd;

  pdfapp_close(app);

  fd = open(filename, O_BINARY | O_RDONLY, 0666);
  if (fd < 0)
    winerror(app, fz_throw("cannot reload file '%s'", filename));

  pdfapp_open(app, filename, fd);
}

static void winopen(void)
{
  xscr = DefaultScreen(xdpy);
  xgc = XCreateGC(xdpy, xwin, 0, nil);
  xa_targets = gdk_atom_intern("TARGETS", False);
  xa_timestamp = gdk_atom_intern("TIMESTAMP", False);
  xa_string = gdk_atom_intern("STRING", False);
  xa_utf8_string = gdk_atom_intern("UTF8_STRING", False);
}

gboolean 
on_keypress_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data) 
{ 
    
  gint x=0, y=0, xadd=0, yadd=0; 
  GdkDisplay *display = NULL; 
  GdkScreen *screen = NULL; 
    
  switch (event->keyval) 
    { 
    case GDK_Left: 
      xadd -= 5; 
      break; 
    case GDK_Right: 
      xadd += 5; 
      break; 
    case GDK_Up: 
      yadd -= 5; 
      break; 
    case GDK_Down: 
      yadd += 5; 
      break;    
    default: 
      return FALSE; /* propogate event */ 
    } 
    
  /* get default display and screen */ 
  display = gdk_display_get_default (); 
  screen = gdk_display_get_default_screen (display); 
    
  /* get cursor position */ 
  gdk_display_get_pointer (display, NULL, &x, &y, NULL); 
    
  /* set new cusor position */ 
  x += xadd; 
  y += yadd; 
  gdk_display_warp_pointer (display, screen, x, y); 
  /* printf("\n pointer x %d y%d\n", x, y); */
  return FALSE;
}


void winblit(pdfapp_t *app){
  if(closing || !dirty)
    return;
  printf("\n in winblit :iscopying %d  justcopied %d",gapp.iscopying, justcopied);
	int x0 = gapp.panx;
	int y0 = gapp.pany;
	int x1 = gapp.panx + gapp.image->w;
	int y1 = gapp.pany + gapp.image->h;

  	/* 
     * XSetForeground(xdpy, xgc, xbgcolor.pixel);
	 * fillrect(0, 0, x0, gapp.winh);
	 * fillrect(x1, 0, gapp.winw - x1, gapp.winh);
	 * fillrect(0, 0, gapp.winw, y0);
	 * fillrect(0, y1, gapp.winw, gapp.winh - y1);
     * 
	 * XSetForeground(xdpy, xgc, xshcolor.pixel);
	 * fillrect(x0+2, y1, gapp.image->w, 2);
	 * fillrect(x1, y0+2, 2, gapp.image->h);
     */

  if (gapp.iscopying || justcopied)
    {
      pdfapp_invert(&gapp, gapp.selr);
      justcopied = 1;
    }

  pdfapp_inverthit(&gapp);
  int drawablex = 0, drawabley = 0;
  gdk_drawable_get_size(gimage->window, &drawablex, &drawabley);
  
  drawable_region->x = gapp.panx;
  drawable_region->y = gapp.pany;
  drawable_region->width = app->image->w;
  drawable_region->height = app->image->h;
  cairo_t *cr;
  cr = gdk_cairo_create (gimage->window);
  /* printf("\n panx %d pany %d w %d h %d winw %d winh %d iw %d ih %d\n", app->panx, app->pany, drawable_region->x, drawable_region->y, app->winw, app->winh, app->image->w, app->image->h); */

  cairo_set_source_surface(cr, image, app->panx, app->pany);
  cairo_rectangle (cr, app->panx, app->pany, app->image->w, app->image->h);
  cairo_fill (cr);
  cairo_destroy(cr);

  pdfapp_inverthit(&gapp);

  if (gapp.iscopying || justcopied)
    {
      pdfapp_invert(&gapp, gapp.selr);
      justcopied = 1;
    }

  if (gapp.isediting)
    {
      char buf[sizeof(gapp.search) + 50];
      sprintf(buf, "Search: %s", gapp.search);
      /* XSetForeground(xdpy, xgc, WhitePixel(xdpy, xs cr));
         fillrect(0, 0, gapp.winw, 30);
         windrawstring(&gapp, 10, 20, buf) */
    }
  dirty = 0;
}


static gboolean
on_expose_cb (GtkWidget      *gimage,
              GdkEventExpose *event,
              gpointer        data)
{
  if(gapp.image)
    dirty = 1;
  winblit(&gapp);
  gtk_widget_set_size_request (gimage, drawable_region->width, drawable_region->height);
  printf("\n event %d\n", event->count);
  return 0;
}


void winloadfile(pdfapp_t *app)
{
  int fd;
  if(image)
    cairo_surface_destroy(image);
  if(app)
    pdfapp_close(app);
  pdfapp_init(&gapp);
  app->scrw = DisplayWidth(xdpy, xscr);
  app->scrh = DisplayHeight(xdpy, xscr);
  int drawablex = 0, drawabley = 0;
  gdk_drawable_get_size(gimage->window, &drawablex, &drawabley);
  printf("\ndrawablex %d drawabley %d",drawablex, drawabley);
  app->resolution = 72;
  app->pageno = 1;
  fd = open(filename, O_BINARY | O_RDONLY, 0666);
  if (fd < 0)
    winerror(app, fz_throw("cannot reload file '%s'", filename));
  printf("\n in load filename %s\n", filename);
  pdfapp_open(app, filename, fd);
  gtk_widget_set_size_request(gimage,  app->image->w, app->image->h);
  /* gtk_create_image(app); */
}

int main( int argc, char *argv[])
{
  struct timeval tmo, tmo_at;
  int c;
  int len;
  char buf[128];
  KeySym keysym;
  int oldx = 0;
  int oldy = 0;
  int resolution = 328;
  int pageno = 1;
  int wasshowingpage;
  int accelerate = 1;

  /* gint width, height; */
  GtkWidget *top_box, *box;
  GtkWidget *toolbar, *toolbar_box;
  GtkUIManager	*ui_manager;
  GtkActionGroup	*action_group;

  gtk_init(&argc, &argv);
  setlocale(LC_NUMERIC, "C");
  /* char *buffer = "%PDF-1.4"; */
  /* printf("\nversion %f\n", atof(buffer+5)*10); */

  gwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_resizable(GTK_WINDOW(gwindow), TRUE);
  gtk_window_set_title(GTK_WINDOW(gwindow), _("Mupdf PDF viewer"));
  gtk_window_set_default_size(GTK_WINDOW(gwindow), 1280, 1024);
  gtk_window_set_resizable (GTK_WINDOW (gwindow), TRUE);
  gtk_window_set_position(GTK_WINDOW(gwindow), GTK_WIN_POS_CENTER);
  /* gtk_window_set_icon(GTK_WINDOW(gwindow), create_pixbuf("gtk_icon.png")); */
  g_signal_connect_swapped(G_OBJECT(gwindow), "destroy",
                           G_CALLBACK(gtk_main_quit), NULL);

  /* gtk_widget_show(gwindow); */

  top_box = gtk_vbox_new(FALSE,0);
  ui_manager = gtk_ui_manager_new();

  drawable_region = gdk_region_new();
  action_group = gtk_action_group_new("PDFViewerActions");
  gtk_action_group_set_translation_domain(action_group, NULL);
  gtk_action_group_add_actions(action_group, menu_entries, G_N_ELEMENTS(menu_entries), NULL);
  gtk_ui_manager_insert_action_group (ui_manager, action_group,0);

  /* gtk_window_add_accel_group(GTK_WINDOW(gwindow), gtk_ui_manager_get_accel_group(ui_manager)); */

  if (!gtk_ui_manager_add_ui_from_string (ui_manager, ui_info, -1, NULL)) {
    g_error("building menus failed");
  }

  gtk_window_add_accel_group (GTK_WINDOW (gwindow), gtk_ui_manager_get_accel_group (ui_manager));
  g_signal_connect (ui_manager, "add-widget", G_CALLBACK (ui_add_widget), top_box);

  gtk_ui_manager_ensure_update (ui_manager);



  toolbar = gtk_toolbar_new();
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar), 
                     gtk_create_item(GTK_STOCK_OPEN, "Open"), 0);
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
                     gtk_create_item(GTK_STOCK_SAVE, "Save"), 1);
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
                     gtk_create_item(GTK_STOCK_ZOOM_IN, "Zoom In"), 1);
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
                     gtk_create_item(GTK_STOCK_ZOOM_OUT, "Zoom out"), 1);
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
                     gtk_create_item(GTK_STOCK_GO_FORWARD, "Next Page"), 1);
  gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
                     gtk_create_item(GTK_STOCK_GO_BACK, "Previous Page"), 1);

  toolbar_box = gtk_handle_box_new();
  gtk_container_add(GTK_CONTAINER(toolbar_box), toolbar);
  gtk_box_pack_start(GTK_BOX(top_box), toolbar_box, FALSE, FALSE, 0);
     
  box = gtk_vbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (top_box), box);
  gtk_container_add(GTK_CONTAINER(gwindow), top_box);
  gimage = gtk_drawing_area_new();
  
  scroll = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll),gimage);

  gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 0);
  gtk_widget_set_events (gimage, GDK_EXPOSURE_MASK
                         | GDK_LEAVE_NOTIFY_MASK
                         | GDK_BUTTON_RELEASE_MASK
                         | GDK_BUTTON_PRESS_MASK
                         | GDK_POINTER_MOTION_MASK
                         | GDK_POINTER_MOTION_HINT_MASK
                         | GDK_CONFIGURE
                         | GDK_SCROLL_MASK
                         | GDK_PROPERTY_NOTIFY
                         );
  gtk_widget_realize(gimage);
  g_signal_connect(G_OBJECT(gimage), "expose-event", G_CALLBACK (on_expose_cb), NULL);
  g_signal_connect(G_OBJECT(gimage), "button-press-event", G_CALLBACK(on_mouse_cb), (gpointer)1);
  g_signal_connect(G_OBJECT(gimage), "button-release-event", G_CALLBACK(on_mouse_cb), (gpointer)-1);
  g_signal_connect(G_OBJECT(gimage), "motion-notify-event", G_CALLBACK(on_mouse_cb), (gpointer)0);  
  g_signal_connect(G_OBJECT(gimage), "scroll-event", G_CALLBACK(on_mousewheel_cb), (gpointer)1);  
  g_signal_connect(G_OBJECT(gimage), "configure-event", G_CALLBACK(on_config_cb), NULL);
  g_signal_connect(G_OBJECT(gimage), "selection-request-event", GTK_SIGNAL_FUNC (on_selreq_cb), NULL);
  
  int drawablex, drawabley;
  gdk_drawable_get_size(gimage->window, &drawablex, &drawabley);
  /* printf("\n x %d y %d \n", drawablex, drawabley, gimage->); */

  xwin = GDK_WINDOW_XID(gimage->window);
  xdpy = GDK_WINDOW_XDISPLAY(gimage->window);
  /* int drawablex, drawabley; */
  winopen();
  
  gtk_widget_show_all(gwindow);
  gtk_main();
  if(cursor) gdk_cursor_unref(cursor);
  pdfapp_close(&gapp);
  return 0;
}
